package StampedLock_16;
import java.util.concurrent.locks.StampedLock;
import java.util.concurrent.locks.Condition;

public class 条件变量转换 {
    private static final StampedLock lock = new StampedLock();
    private static boolean condition = false;
    private static final int WAITER_COUNT = 3;
    private static final int NOTIFIER_COUNT = 2;

    public static void main(String[] args) {
        // 创建等待线程
        for (int i = 0; i < WAITER_COUNT; i++) {
            final int waiterId = i;
            new Thread(new Runnable() {
                public void run() {
                    waitForCondition(waiterId);
                }
            }, "Waiter-" + i).start();
        }

        // 创建通知线程
        for (int i = 0; i < NOTIFIER_COUNT; i++) {
            final int notifierId = i;
            new Thread(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(500 + notifierId * 200);
                        changeCondition(notifierId);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "Notifier-" + i).start();
        }
    }

    private static void waitForCondition(int waiterId) {
        long stamp = lock.readLock();
        try {
            while (!condition) {
                System.out.println(Thread.currentThread().getName() + " 条件不满足，等待");
                // 转换为写锁以使用条件变量
                long writeStamp = lock.tryConvertToWriteLock(stamp);
                if (writeStamp != 0L) {
                    stamp = writeStamp;
                    Condition cond = lock.asWriteLock().newCondition();
                    try {
                        cond.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    lock.unlockRead(stamp);
                    stamp = lock.writeLock();
                }
            }
            System.out.println(Thread.currentThread().getName() + " 条件满足，继续执行");
        } finally {
            lock.unlock(stamp);
        }
    }

    private static void changeCondition(int notifierId) {
        long stamp = lock.writeLock();
        try {
            System.out.println(Thread.currentThread().getName() + " 开始修改条件");
            Thread.sleep(100); // 模拟操作耗时
            condition = true;
            Condition cond = lock.asWriteLock().newCondition();
            cond.signalAll();
            System.out.println(Thread.currentThread().getName() + " 已通知所有等待线程");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlockWrite(stamp);
        }
    }
}